#include "trm/param.h"
#include <std_min_max.h>

namespace trm {

param const default_param = {
	1, //reference_frame_pitch
	1, //downsample

	false, //optic_flow
	10, //max_motion
	8, //tracker_size

	false, //mincut
	2, //mincut_pyramid_levels
	mincut::source_target, //mincut_information_source
	2, //mincut_max_motion
	5, //mincut_max_link_distance
	5, //mincut_link_count
	10, //mincut_aspect
	5, //mincut_interframe_max_link_distance
	4, //mincut_interframe_link_count
	false, //mincut_antialiasing
	2, //mincut_antialiasing_levels_exp

/*	false, //entropic_tracker
	3, //entropic_best_move_iter_num
	10, //entropic_move_radius
	15, //entropic_band_radius
	0.55f, //entropic_unambig_thr
	1.5f, //entropic_alpha
	true, //entropic_sqrt_control
	false, //entropic_safe_time_step*/

	true, //refine_mask
	refine::source_both, //refine_information_source
	10, //refine_window_half_size
	false, //refine_auto
	3.5f, //refine_enough_statistics
	refine::prefer_none, //refine_preference

	false, //refine2_mask
	5, //refine2_max_motion
	3, //refine2_max_level

/*	false, //refine3_mask
	refine::source_both, //refine3_information_source
	5.0f, //refine3_enough_statistics
	refine::prefer_none, //refine3_preference*/

	0, //dilation_erosion
	0, //wool_removal

	false, //decrease_mask_freedom
	7, //decrease_freedom_degrees
	true, //decrease_smooth_contour
	50, //decrease_iterations
	0, //decrease_nodes_traction
	0.2, //decrease_tangents_traction

	smooth_mask_off, //smooth_mask
	1, //smooth_window_half_size
	7, //smooth_passes_num
	5, //smooth_max_condition_number
	//2, //smooth_fore_depth
	//2, //smooth_back_depth
	//0.03f, //smooth_sharpness
	//3, //smooth_noisiness
	true //smooth_decorative
};

void param::set_default_values()
{
	* this = default_param;
}

template <typename T>
inline void bottom_limit(T & v, T limit)
	{ if (v < limit) v = limit; }

template <typename T>
inline void top_limit(T & v, T limit)
	{ if (v > limit) v = limit; }

template <typename T>
inline void limit(T & v, T bottom, T top)
	{ bottom_limit(v, bottom); top_limit(v, top); }

void param::put_within_the_limits()
{
	bottom_limit(reference_frame_pitch, 1);
	limit(downsample, 1, 4);

	limit(max_motion, 1, 100);
	limit(tracker_size, 1, 100);

	limit(mincut_pyramid_levels, 0, 5);
	limit(mincut_max_motion, 1, 100);
	limit(mincut_max_link_distance, 1, 60);
	limit(mincut_link_count, 1, mincut_total_window_pixels());
	bottom_limit(mincut_aspect, 0.0f);
	limit(mincut_interframe_max_link_distance, 1, 60);
	limit(mincut_interframe_link_count, 1, mincut_total_interframe_window_pixels());
	limit(mincut_antialiasing_levels_exp, 0, 6);

/*	limit(entropic_best_move_iter_num, 1, 10);
	limit(entropic_move_radius, 3, 50);
	limit(entropic_band_radius, 3, 50);
	limit(entropic_unambig_thr, 0.5f, 1.0f);
	limit(entropic_alpha, 0.01f, 10000.0f);*/

	limit(refine_window_half_size, 1, 60);
	limit<float>(refine_enough_statistics, 1, std::max(refine_total_window_pixels()/3-2, 7));

	limit(refine2_max_motion, 1, 100);
	limit(refine2_max_level, 1, 5);

	//limit<float>(refine3_enough_statistics, 1, 30);

	limit(dilation_erosion, -25, 25);
	limit(wool_removal, 0, 25);

	limit(decrease_freedom_degrees, 2, 100);
	limit(decrease_iterations, 25, 10000);
	limit(decrease_nodes_traction, 0.0f, 0.9f);
	limit(decrease_tangents_traction, 0.0f, 0.9f);

	limit(smooth_window_half_size, 1, 50);
	limit(smooth_passes_num, 1, 1000);
	limit(smooth_max_condition_number, 2, 100);
	//limit(smooth_fore_depth, 0, 30);
	//limit(smooth_back_depth, 0, 30);
	//limit(smooth_sharpness, 0.0f, 1.0f);
	//limit(smooth_noisiness, 0.0f, 100.0f);
}

bool operator == (param const & lhs, param const & rhs)
{
	if (lhs.reference_frame_pitch != rhs.reference_frame_pitch ||
		lhs.downsample != rhs.downsample)
		return false;

	if (lhs.optic_flow != rhs.optic_flow)
		return false;
	if (lhs.optic_flow) {
		if (lhs.max_motion != rhs.max_motion || lhs.tracker_size != rhs.tracker_size)
			return false;
	}

	if (lhs.mincut != rhs.mincut)
		return false;
	if (lhs.mincut) {
		if (lhs.mincut_pyramid_levels != rhs.mincut_pyramid_levels ||
			lhs.mincut_information_source != rhs.mincut_information_source ||
			lhs.mincut_max_motion != rhs.mincut_max_motion ||
			lhs.mincut_max_link_distance != rhs.mincut_max_link_distance ||
			lhs.mincut_link_count != rhs.mincut_link_count ||
			lhs.mincut_aspect != rhs.mincut_aspect ||
			lhs.mincut_antialiasing != rhs.mincut_antialiasing)
			return false;
		if (lhs.mincut_antialiasing)
			if (lhs.mincut_antialiasing_levels_exp != rhs.mincut_antialiasing_levels_exp)
				return false;
		if (lhs.mincut_information_source) {
			if (lhs.mincut_interframe_link_count != rhs.mincut_interframe_link_count ||
				lhs.mincut_interframe_max_link_distance != rhs.mincut_interframe_max_link_distance)
				return false;
		}
	}

/*	if (lhs.entropic_tracker != rhs.entropic_tracker)
		return false;
	if (lhs.entropic_tracker) {
		if (lhs.entropic_best_move_iter_num != rhs.entropic_best_move_iter_num ||
			lhs.entropic_move_radius != rhs.entropic_move_radius ||
			lhs.entropic_band_radius != rhs.entropic_band_radius ||
			lhs.entropic_unambig_thr != rhs.entropic_unambig_thr ||
			lhs.entropic_alpha != rhs.entropic_alpha ||
			lhs.entropic_sqrt_control != rhs.entropic_sqrt_control ||
			lhs.entropic_safe_time_step != rhs.entropic_safe_time_step)
			return false;
	}*/

	if (lhs.refine_mask != rhs.refine_mask)
		return false;
	if (lhs.refine_mask) {
		if (lhs.refine_information_source != rhs.refine_information_source ||
			lhs.refine_window_half_size != rhs.refine_window_half_size ||
			lhs.refine_auto != rhs.refine_auto)
			return false;
		if (!lhs.refine_auto) {
			if (lhs.refine_enough_statistics != rhs.refine_enough_statistics ||
				lhs.refine_preference != rhs.refine_preference)
				return false;
		}
	}

	if (lhs.refine2_mask != rhs.refine2_mask)
		return false;
	if (lhs.refine2_mask) {
		if (lhs.refine2_max_motion != rhs.refine2_max_motion ||
			lhs.refine2_max_level != rhs.refine2_max_level)
			return false;
	}

	/*if (lhs.refine3_mask != rhs.refine3_mask)
		return false;
	if (lhs.refine3_mask) {
		if (lhs.refine3_information_source != rhs.refine3_information_source ||
			lhs.refine3_enough_statistics != rhs.refine3_enough_statistics ||
			lhs.refine3_preference != rhs.refine3_preference)
			return false;
	}*/

	if (lhs.dilation_erosion != rhs.dilation_erosion ||
		lhs.wool_removal != rhs.wool_removal)
		return false;

	if (lhs.decrease_mask_freedom != rhs.decrease_mask_freedom)
		return false;
	if (lhs.decrease_mask_freedom) {
		if (lhs.decrease_freedom_degrees != rhs.decrease_freedom_degrees ||
			lhs.decrease_smooth_contour != rhs.decrease_smooth_contour ||
			lhs.decrease_iterations != rhs.decrease_iterations ||
			lhs.decrease_nodes_traction != rhs.decrease_nodes_traction ||
			lhs.decrease_tangents_traction != rhs.decrease_tangents_traction)
			return false;
	}

	if (lhs.smooth_mask != rhs.smooth_mask)
		return false;
	if (lhs.smooth_mask) {
		if (lhs.smooth_window_half_size != rhs.smooth_window_half_size ||
			lhs.smooth_passes_num != rhs.smooth_passes_num ||
			lhs.smooth_max_condition_number != rhs.smooth_max_condition_number ||
			//lhs.smooth_fore_depth != rhs.smooth_fore_depth ||
			//lhs.smooth_back_depth != rhs.smooth_back_depth ||
			//lhs.smooth_sharpness != rhs.smooth_sharpness ||
			//lhs.smooth_noisiness != rhs.smooth_noisiness ||
			lhs.smooth_decorative != rhs.smooth_decorative
		)
			return false;
	}

	return true;
}

} //namespace trm
